<?php
/*
 * 自定义模型默认父类,负责与数据库类协调
 * 数据库类包括两个类：
 *   1、数据库抽象类DB类(驱动类的抽象层)。负责抽象方法的实现如select抽象函数、拼接sql语句等
 *   2、驱动类。即底层类,里面的包含所有的与该数据库相关的数据库函数或与其相关的特性，如mysql_query或pdo::prepare()等等
 *   
 *   
 *   
 *   
 *   model类
 *         1、把所有的参数分门别类,即把自定义模型调用传递过来的参数分类,如把属于跟field相关的参数放到
 *       field关联数组中去,把属于跟where相关条件的参数放到where关联数组中去。。
 *         2、还有取表的完整名称
 *         3、处理变量的空值、为设置等情况,让它转化为自定义的一个固定值
 *         4、设置自定义模型调用的方法如,select,find,insert,delete,update...
 *   db类(Driver的抽象类也是父类)
 *         1、负责把传递过来的数组(如field关联数组,where关联数组)拼接,单单是数组变量间的拼接,如'field'='id,name'或
 *       'feild'=>array('id','name'),拼接后成'id,name',最后把sql语句原型中的特殊标志替换成拼接好的字符串,sql原型在驱动类中,
 *       如sql='SELECT %DISTINCT% %FIELD% FROM %TABLE% %JOIN% %WHERE% %GROUP% %HAVING% %ORDERBY% %LIMIT% %UNION%';
 *         2、处理sql语句执行后返回的资源,如mysql中的获取记录mysql_fetch_assoc(),
 *  Driver类
 *       1、sql语句的原型,如sql='SELECT %DISTINCT% %FIELD% FROM %TABLE% %JOIN% %WHERE% %GROUP% %HAVING% %ORDERBY% %LIMIT% %UNION%';
 *       该语句放在此主要考虑不同的数据库sql语句有所差异,tinkphp放在db类中
 *       2、在此使用所有的与该数据库相关的类方法或函数
 * */


//暂时没有连贯操作
class Model extends Object{
    private   $_db=null;
    protected $tabName='';  //表名没前缀
    protected $oriTabName='';  //完整的表名,有前缀
     
    public function _initialize($params=array()){
        global $cfg;
        static $tabName='';
        if (empty($tabName)) {
            $this->oriTabName=$this->getTabName();
        }
        $driver=strtolower($cfg['db_type']);
        $className='D'.ucfirst($driver);
        if (is_null($this->_db)){
            include_once APP_LIB.'db.php';
            include_once APP_LIB.'pdo.php';
            $this->_db=new $className($this->oriTabName);
        }
    }
    
    
    //添加操作
    public function add($data,$options=array()){
        $options=array_merge($options,$this->_explainOption($options));
        if (!empty($data))
            return $this->_db->insert($data,$options);
        return false;
    }

    //查询操作
    public function select($conditions=array()){
        $options=$this->_explainOption($conditions);
        if (is_array($conditions))
            return $this->_db->select($options);
        return false;
    }
    
    //获取一条记录
    public function find($conditon=array()){
        $options=$this->_explainOption($conditon);
        if (is_array($conditon))
            return $this->_db->select($options,false);
        return false;
    }
    
    
    //更新操作
    public function update($condition=array()){
        $options=$this->_explainOption($condition);
        if (is_array($condition))
            return $this->_db->update($options);
        return false;
    }
    //删除操作
    public function delete($condition=array()){
    	$options=$this->_explainOption($condition);
    	if (is_array($condition))
    	    return $this->_db->delete($options);
    	return false;
    }
    
    
    /*
     * @author luguo
     * @param array $condition 查询条件
     * @return bool
     * 
     * 
     * */    
    public function r_select($condition){
        if (is_array($condition)){
          $options=$this->_explainOption($condition);
          return $this->_db->r_select($options);
        }
        return false;
    }
    
    //设置属性
    public function setAttr($value){
        $this->_db->setAttr($value);
    }
    
    /*
     * @param array $options 
     * @return mix
     * */
    private function _explainOption($options=array()){
        global $cfg;
        isset($options['distinct']) || $options['distinct']='';
        isset($options['field']) || $options['field']='';
        isset($options['table']) || $options['distinct']='';
        isset($options['join']) || $options['join']='';
        isset($options['where']) || $options['where']='';
        isset($options['group']) || $options['group']='';
        isset($options['having']) || $options['having']='';
        isset($options['orderby']) || $options['orderby']='';
        isset($options['limit']) || $options['limit']='';
        isset($options['union']) || $options['union']='';
        if (empty($options['field'])){
            $options['field']='*';
        }else {
            $options['field']=is_array($options['field'])?implode(',', $options['field']):$options['field'];
        }
        if (empty($options['table'])){
            $options['table']=$this->oriTabName;
        }
        
        if (!empty($options['limit']) && is_array($options['limit'])){
        	count($options['limit'])>2 && $options['limit']='';
        }elseif (!empty($options['limit']) && is_string($options['limit'])){
        	$options['limit']=explode(',', $options['limit']);
        	count($options['limit'])>2 && $options['limit']='';
        }
        
        //第一个参数为关联表名;第二个为字段名;第三个从表的外键(不是主表);第四个主要用于一对多关系中更好的完整读取记录
        if (!empty($options['join']) && is_array($options['join'])){
        	$join=array();
            foreach ($options['join'] as $jKey=>$jVal){
                if (!is_array($jVal) || count($jVal)==0)continue;
               $join['join'][$jKey]['table']=isset($jVal[0])?$jVal[0]:'';
            $join['join'][$jKey]['field']=isset($jVal[1])?$jVal[1]:'';
            $join['join'][$jKey]['fpk']=isset($jVal[2])?$jVal[2]:'';
            if (isset($jVal[3]) ){
                //第一个参数子数组下标，第二个参数子数组记录排列方式(可选)，第三个限制子数组记录个数(可选)，第四个子数组查询where的条件(可选)
                if (is_array($jVal[3]) && count($jVal[3])<=4){
                    $join['join'][$jKey]['sub']['index']=isset($jVal[3][0])?$jVal[3][0]:'';
                    $join['join'][$jKey]['sub']['orderby']=isset($jVal[3][1])?$jVal[3][1]:'';
                    $join['join'][$jKey]['sub']['limit']=isset($jVal[3][2])?$jVal[3][2]:'';
                    $join['join'][$jKey]['sub']['where']=isset($jVal[3][3])?$jVal[3][3]:array();
                }elseif (is_string($jVal[3])){
                    //主表的字段
                    $join['join'][$jKey]['sub']=$jVal[3];
                }
            }
            //unset($options['join'][$jKey]);
           }
           $options['join']=$join['join'];
        }else {
        	$options['join']='';
        }
       return $options;
    
    
    }
    
    //去完整的表名
    private function getTabName($name=''){
        global $cfg;
        $tabName=empty($name)?substr(get_class($this),0,-5):$name;
        $tabName=preg_replace('/([A-Z]+)/', '_\\1', $tabName);
        $tabName=strtolower(trim($tabName,'_'));
        $this->tabName=$tabName;
        return $cfg['db_pre'].$tabName;
    }
    
    private function _explainOption2($options=array()){
        global $cfg;
        if (!isset($options['table'])){
            $options['table']=$this->oriTabName;
        }
        $options['data']=isset($options['data']) && !empty($options['data'])?$options['data']:array();
        
        $options['where']=empty($options['where'])?array():$options['where'];
        
        $options['field']=!isset($options['field'])?'*':$options['field'];
        
        $options['orderby']=(isset($options['orderby'])&&is_string($options['orderby']))?$options['orderby']:'';
        
        return $options;
    }

    public function getPageCount(){
    	return $this->_db->getPageCount();
    }


}